﻿using System.Collections.ObjectModel;
using System.Reflection;
using System.Windows.Navigation;
using Budget.Silver.Core.Controls;
using Budget.Silver.Core.Messages;
using Budget.Silver.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Threading;

namespace Budget.Silver.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        #region Members data

        private bool isBusy;
        private string errorMessage;

        private RelayCommand<NavigationEventArgs> navigatedCommand;
        private RelayCommand<NavigationFailedEventArgs> navigationFailedCommand; 

        #endregion

        #region Binding data

        public string Version 
        { 
            get
            {
                var assembly = Assembly.GetExecutingAssembly();
                var version = new AssemblyName(assembly.FullName).Version.ToString();
                string config;
#if DEBUG
                config = "DEBUG";
#else
                config = "RELEASE";
#endif
                return string.Format("(v{0} - {1})", version, config);
            }
        }

        public string ErrorMessage
        {
            get { return errorMessage; }
            private set
            {
                if (errorMessage != value)
                {
                    errorMessage = value;

                    RaisePropertyChanged(() => ErrorMessage);

                    MessengerInstance.Send(new ErrorDetailsMessage(ErrorMessage));
                }
            }
        }

        public bool IsBusy
        {
            get { return isBusy; }
            private set
            {
                if (isBusy != value)
                {
                    isBusy = value;
                    RaisePropertyChanged(() => IsBusy);
                }
            }
        }

        public ObservableCollection<NavigationLinkModel> Links { get; private set; } 

        public RelayCommand<NavigationEventArgs> Navigated
        {
            get { return navigatedCommand; }
        }

        public RelayCommand<NavigationFailedEventArgs> NavigationFailed
        {
            get { return navigationFailedCommand; }
        }

        #endregion

        #region Public methods

        public MainViewModel()
        {
            MessengerInstance.Register<BusyMessage>(this, BusyReceived);
            MessengerInstance.Register<ExceptionMessage>(this, ExceptionReceived);

            Links = Menu.Create();

            CreateCommands();
        }

        #endregion

        #region Commands

        private void CreateCommands()
        {
            navigatedCommand = new RelayCommand<NavigationEventArgs>(NavigatedCommand);
            navigationFailedCommand = new RelayCommand<NavigationFailedEventArgs>(NavigationFailedCommand);
        }

        private void NavigatedCommand(NavigationEventArgs e)
        {
            foreach (var link in Links)
            {
                link.CurrentState = link.PageUri.Equals(e.Uri.ToString()) || (link.IsDefault && string.IsNullOrEmpty(e.Uri.ToString())) ? "ActiveLink" : "InactiveLink";
            }
        }

        private void NavigationFailedCommand(NavigationFailedEventArgs e)
        {
            e.Handled = true;

            var exc = new ExceptionMessage(e.Exception);
            ErrorMessage = exc.FullMessage;
        }

        #endregion

        #region Messaging

        private void BusyReceived(BusyMessage msg)
        {
            DispatcherHelper.UIDispatcher.BeginInvoke(() => IsBusy = msg.Content);
        }

        private void ExceptionReceived(ExceptionMessage msg)
        {
            DispatcherHelper.UIDispatcher.BeginInvoke(() => ErrorMessage = msg.FullMessage);
        }

        #endregion
    }
}